package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
)

type command struct {
	l *schema
}

//help list CmdHelp 在 6_config.go中。
func (c *command) Help(args []string) int {
	for _, row := range cmdHelp {
		s := fmt.Sprintf("%s %s\n", "NO:"+row.No, row.Msg)
		fmt.Print(s)
	}
	return 0
}

//清屏
func (c *command) Clean(args []string) int {
	clean()
	return 0
}

//退出
func (c *command) Quit(args []string) int {
	return 1
}

// Handlers 映射相应的命令，命令处理器，该方法是所有命令的入口。
//  在这个方法里新增或者删除命令。
func (c *command) Handlers() map[string]func(args []string) int {
	return map[string]func(args []string) int{
		//"0":     c.CustomDir,     // 设置构建目录
		"1": c.MarkDown, // 生成 MarkDown 文档
		"2": c.Model,    // 根据数据库中的表生成表的实体层代码
		"3": c.Dao,      // 根据数据库中的表生成dao层代码
		//"4":     c.Frame,         // 生成mvc基础代码
		//"5":     c.ShowTableList, // 查找或者设置表名
		"clear": c.Clean,
		"help":  c.Help,
		"quit":  c.Quit,
	}
}

//CustomDir 自定义生成目录 命令编号 0
func (c *command) CustomDir(args []string) int {
	fmt.Print("请输入您要存放生成的文件的目录地址，请注意该目录地址的权限")
	line, _, _ := bufio.NewReader(os.Stdin).ReadLine()
	if string(line) != "" {
		path, err := c.l.GenerateDir(string(line)) // GenerateDir() 在 tool.go 中
		if err == nil {
			c.l.path = path
			fmt.Println("设置目录成功!>>", path)
		} else {
			log.Println("设置目录失败!>>", err)
		}
	}
	return 0
}

// MarkDown 生成数据库表的markdown文档 命令编号 1
func (c *command) MarkDown(args []string) int {
	fmt.Println("准备生成==>markdown文件...")
	//检查目录是否存在
	c.l.createDir(c.l.path)
	err := c.l.CreateMarkdown()
	if err != nil {
		log.Println("MarkDown>>", err)
	}
	return 0
}

// Dao 命令编号为 3
// dao层放的是操作数据库表的具体 CRUD 方法!
func (c *command) Dao(args []string) int {
	c.l.CreateAllDao()                // 该函数在 8_logic.go中
	go c.l.gofmt(c.l.getExeRootDir()) //该函数在 tool.go 中
	return 0
}

// Model 在dao层:生成数据库表对应的结构实体，命令编号为 2
func (c *command) Model(args []string) int {
	c.l.CreateAllModel()              // 该函数在 8_logic.go中
	go c.l.gofmt(c.l.getExeRootDir()) //该函数在 tool.go 中
	return 0
}

//setTag 设置结构体字段上的 Tag
func (c *command) setTag() []string {
	fmt.Print("请设置结构体字段的 TagName，以逗号分隔 (例如 :json,form,uri)>")
	input, _, _ := bufio.NewReader(os.Stdin).ReadLine() // 从终端读取一行输入的数据。
	if string(input) != "" {
		formatList := c.l.checkCharDoSpecial(string(input), ',', `[\w\,\-]+`) // 该方法在 tool.go 中
		if len(formatList) > 0 {
			fmt.Printf("设置Tag成功: %v\n", formatList)
			return formatList
		}
	}
	fmt.Println("设置失败!")
	return nil
}

//defaultTag 设置结构体的字段上的 Tag
func (c *command) defaultTag() []string {
	//tagStr := "json,form,v,db"
	tagStr := "json"
	input := []byte(tagStr)
	formatList := c.l.checkCharDoSpecial(string(input), ',', `[\w\,\-]+`)
	if len(formatList) > 0 {
		return formatList
	}
	return nil
}

//显示所有的表名
func (c *command) ShowTableList(args []string) int {
	if len(c.l.tables) == 0 {
		fmt.Println("哎呀，什么都没有!!!")
		return 0
	}
	c.showTableList(c.l.tables)
	fmt.Print("请输入您需要查询的表序号: (默认情况下全部，以逗号分隔)")
	line, _, _ := bufio.NewReader(os.Stdin).ReadLine()
	if !strings.EqualFold(string(line), "") {
		c.l.doTables = c.filterTables(string(line), c.l.tables)
	}
	return 0
}

//显示所有名视图
func (c *command) showTableList(args []table) {
	for idx, table := range args {
		idx++
		info := fmt.Sprintf("%s:%s", strconv.Itoa(idx), table.Name)
		if table.Comment != "" {
			info += fmt.Sprintf("(%s)", table.Comment)
		}
		fmt.Println(info)
	}
	fmt.Println("总表数:" + strconv.Itoa(len(args)) + "\n")
}

//过滤表名
func (c *command) filterTables(ids string, tables []table) []table {
	lst := strings.Split(ids, ",")
	result := make([]table, 0)
	if strings.ToLower(ids) == "all" {
		return tables
	}
	for _, id := range lst {
		id = strings.TrimSpace(id)
		for _, t := range tables {
			if strconv.Itoa(t.Index) == id || id == t.Name {
				result = append(result, t)
			}
		}
	}
	return result
}

// Frame 生成mvc框架基础代码，依次生成 router层，service层，controller层，dto层代码。，命令编号为 2
//func (c *command) Frame(args []string) int {
//	err := c.l.CreateFrame() // 该函数在 8_logic.go中
//	if err != nil {
//		log.Println("生成mvc基础代码失败!", err.Error())
//	}
//	go c.l.gofmt(c.l.getExeRootDir()) //该函数在 tool.go 中 格式化go文件内的代码，将 xxx.go 文件里的代码变成符合 go文件规范的代码。
//	return 0
//}
